import type { ContextMenuEntry, ContextMenuItem, ContextMenuOptions } from './types'

// const defaultMaxHeight = 300
const defaultMinWidth = 100
const defaultMaxWidth = 300

function makeMenuItem(item: ContextMenuItem, opt: ContextMenuOptions): HTMLElement {
  const div = document.createElement('div')
  div.classList.add('cm-item')
  // const a = document.createElement('div')
  // a.classList.add('cm-text')
  // a.textContent = item.text
  div.appendChild(makeMenuItemRow(item))
  if (item.children) {
    div.classList.add('has-list')
    div.appendChild(makeMenuList(item.children, opt))
  }
  return div
}

function makeMenuItemRow(item: ContextMenuItem): HTMLElement {
  const div = document.createElement('div')
  div.classList.add('cm-row')
  if (item.icon) {
    const i = document.createElement('i')
    i.classList.add(item.icon)
    div.appendChild(i)
  }
  const a = document.createElement('span')
  a.classList.add('cm-text')
  a.textContent = item.text
  div.appendChild(a)
  if (item.children) {
    const a = document.createElement('i')
    a.classList.add('mas-icon-start')
    // const a = document.createElement('span')
    // a.textContent = '>'
    a.classList.add('cm-arrow')
    div.appendChild(a)
    div.onmousedown = (evt: MouseEvent) => {
      evt.preventDefault()
      evt.stopPropagation()
    }
  } else if (item.onClick) {
    div.onmousedown = item.onClick
  }
  return div
}

function makeMenuItemLabel(item: ContextMenuItem): HTMLElement {
  const div = document.createElement('div')
  div.classList.add('cm-label')
  if (item.icon) {
    const i = document.createElement('i')
    i.classList.add(item.icon)
    div.appendChild(i)
  }
  const a = document.createElement('span')
  a.textContent = item.text
  div.appendChild(a)
  div.onmousedown = (evt: MouseEvent) => {
    evt.preventDefault()
    evt.stopPropagation()
  }
  return div
}

function makeMenuEntry(e: ContextMenuEntry, opt: ContextMenuOptions): HTMLElement {
  if (typeof e === 'string') {
    if (e === '-') {
      return document.createElement('hr')
    }
    const div = document.createElement('div')
    div.classList.add('cm-label')
    div.textContent = e
    div.onmousedown = (evt: MouseEvent) => {
      evt.preventDefault()
      evt.stopPropagation()
    }
    return div
  }
  const e1 = e as ContextMenuItem
  if (!e1.onClick && (!e1.children || e1.children.length === 0)) {
    return makeMenuItemLabel(e1)
  }
  return makeMenuItem(e1, opt)
}

function makeMenuList(lst: ContextMenuEntry[], opt: ContextMenuOptions): HTMLElement {
  const div = document.createElement('div')
  div.classList.add('cm-list')
  div.style.minWidth = opt.minWidth + 'px'
  div.style.maxWidth = opt.maxWidth + 'px'
  for (const e of lst) {
    div.appendChild(makeMenuEntry(e, opt))
  }
  return div
}

export interface ContextMenuOptionsX extends ContextMenuOptions {
  items: ContextMenuEntry[]
  x: number
  y: number
}

export function openContextMenuX(lst: ContextMenuEntry[], evt: MouseEvent, o?: ContextMenuOptions) {
  openContextMenu(lst, evt.clientX, evt.clientY, o)
}

export function openContextMenu(
  lst: ContextMenuEntry[],
  x: number,
  y: number,
  o?: ContextMenuOptions
) {
  const opt = fixOpt(o)
  const menu = makeMenuList(lst, opt)
  menu.style.left = x + 'px'
  menu.style.top = y + 'px'
  if (opt.maxHeight) {
    menu.style.maxHeight = opt.maxHeight + 'px'
  }
  document.body.appendChild(menu)
  const hide = () => {
    document.removeEventListener('mousedown', hide, true)
    document.body.removeChild(menu)
  }
  document.addEventListener('mousedown', hide, true)
}

function fixOpt(opt?: ContextMenuOptions): ContextMenuOptions {
  let o: ContextMenuOptions
  if (!opt) {
    o = {}
  } else o = opt
  if (!o.minWidth) {
    o.minWidth = defaultMinWidth
  }
  if (!o.maxWidth) {
    o.maxWidth = defaultMaxWidth
  }
  return o
}
